#include <stdio.h>
#include <stdint.h>
#include <ringbuffer8.h>


struct ringbuffer8
{
    uint32_t head;
    uint32_t tail;
    uint32_t length;

    uint8_t buff[];
};


ringbuffer8_t rb8_init(uint8_t *buff, uint32_t size)
{
    ringbuffer8_t rb = (ringbuffer8_t)buff;
    rb->head = rb->tail = 0;
    rb->length = size - sizeof(struct ringbuffer8);

    return rb;
}

static inline uint16_t next_head(ringbuffer8_t rb)
{
    return rb->head + 1 < rb->length ? rb->head + 1 : 0;
}

static inline uint16_t next_tail(ringbuffer8_t rb)
{
    return rb->tail + 1 < rb->length ? rb->tail + 1 : 0;
}

bool rb8_empty(ringbuffer8_t rb)
{
    return rb->head == rb->tail;
}

bool rb8_full(ringbuffer8_t rb)
{
    return next_head(rb) == rb->tail;
}

bool rb8_put(ringbuffer8_t rb, uint8_t data)
{
    if (rb8_full(rb))
        return false;

    rb->buff[rb->head] = data;
    rb->head = next_head(rb);

    return true;
}

bool rb8_puts(ringbuffer8_t rb, uint8_t *data, uint32_t size)
{
    bool ret = true;

    if (rb8_full(rb))
        return false;

    for (uint32_t i = 0; i < size && ret; i++)
    {
        ret = rb8_put(rb, data[i]);
    }

    return ret;
}

bool rb8_get(ringbuffer8_t rb, uint8_t *data)
{
    if (rb8_empty(rb))
        return false;

    *data = rb->buff[rb->tail];
    rb->tail = next_tail(rb);

    return true;
}

bool rb8_gets(ringbuffer8_t rb, uint8_t *data, uint32_t size)
{
    bool ret = true;
    if (rb8_empty(rb))
        return false;

    for (uint32_t i = 0; i < size && ret; i++)
    {
        ret = rb8_get(rb, &data[i]);
    }

    return ret;
}
